#lang sicp
;练习3.1
;累加器
(define (make-accumulator value)
  (lambda (a)
    (begin (set! value (+ value a))
           value)))
;(define A (make-accumulator 5))
;(A 10)
;(A 10)

;--------------------------------------------------------
;练习3.2
;过程调用次数
(define (make-monitored f)
  (let ((count 0))
    (define (mf p)
      (cond ((eq? p 'how-many-calls?) count)
            ((eq? p 'reset-count) (set! count 0))
            (else (begin (set! count (+ count 1))
                         (f p)))))
    mf))

(define s (make-monitored sqrt))
;(s 100)
;(s 'how-many-calls?)

;-------------------------------------------------------------
;流
(define (stream-ref s n)
  (if (= n 0)
      (stream-car s)
      (stream-ref (stream-cdr s) (- n 1))))
(define (stream-map proc s)
  (if (stream-null? s)
      the-empty-stream
      (cons-stream (proc (stream-car s))
                   (stream-map proc (stream-cdr s)))))
(define (stream-for-each proc s)
  (if (stream-null? s)
      'done
      (begin (proc (stream-car s))
             (stream-for-each proc (stream-cdr s)))))
(define (display-stream s)
  (stream-for-each display-line s))
(define (display-line x)
  (newline)
  (display x))
(define (stream-car stream) (car stream))
(define (stream-cdr stream) (force (cdr stream)))
(define (stream-enumerate-interval low high)
  (if (> low high)
      the-empty-stream
      (cons-stream
       low
       (stream-enumerate-interval (+ low 1) high))))
(define (stream-filter pred stream)
  (cond ((stream-null? stream) the-empty-stream)
        ((pred (stream-car stream))
         (cons-stream (stream-car stream)
                      (stream-filter pred
                                     (stream-cdr stream))))
        (else (stream-filter pred (stream-cdr stream)))))
;--------------------------------------------------
;练习3.51
(define (show x)
  (display-line x))
(define x-3.51 (stream-map show (stream-enumerate-interval 0 10)))
;(stream-ref x-3.51 2)
;(stream-ref x-3.51 7)

;----------------------------------------------------
(define (stream-map-general proc s1 s2)
    (if (or (stream-null? s1) (stream-null? s2))
      the-empty-stream
      (cons-stream (proc (stream-car s1) (stream-car s2))
                   (stream-map-general proc
                                       (stream-cdr s1)
                                       (stream-cdr s2)))))
(define (add-streams s1 s2)
  (stream-map-general + s1 s2))
(define ones (cons-stream 1 ones))
(define integers (cons-stream 1 (add-streams ones integers)))
(define (scale-stream stream factor)
  (stream-map (lambda (x) (* x factor)) stream))

;------------------------------------------------------
;练习3.53
(define s-3.53 (cons-stream 1 (add-streams s-3.53 s-3.53)))
;(stream-ref (stream-map show s-3.53) 10)

;------------------------------------------------------
;练习3.54
(define (mul-streams s1 s2)
  (stream-map-general * s1 s2))
(define factorials (cons-stream 1 (mul-streams factorials integers)))
;(stream-ref (stream-map show factorials) 5)

;---------------------------------------------------
;练习3.55
(define (partial-sums s)
  (cons-stream (stream-car s)
               (add-streams (stream-cdr s) (partial-sums s))))
;(stream-ref (stream-map show (partial-sums integers)) 5)

;---------------------------------------------------
;练习3.59
;a)
(define (integrate-series s)
  (mul-streams s
               (stream-map (lambda (x) (/ 1 x))
                           integers)))
;(stream-ref (stream-map show (integrate-series integers)) 5)

;b)
(define cosine-series
  (cons-stream 1
               (stream-map (lambda (x) (* -1 x))
                           (integrate-series sine-series))))
(define sine-series
  (cons-stream 1
               (integrate-series cosine-series)))

;---------------------------------------------
;带反馈的加法器流
(define (integral delayed-integrand initial-value dt)
  (define int
    (cons-stream initial-value
                 (let ((integrand (force delayed-integrand)))
                   (add-streams (scale-stream integrand dt)
                              int))))
  int)

;-----------------------------------------------
;练习3.73
;RC电路流模拟
(define (RC R C dt)
  (lambda (i v0)
    (add-streams (scale-stream i R)
                 (integral (scale-stream i (/ 1 C))
                           v0
                           dt))))
